package com.sdy.resdir.web.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sdy.auth.api.model.UserInfo;
import com.sdy.auth.client.service.SsoService;
import com.sdy.common.model.BizException;
import com.sdy.common.model.Response;
import com.sdy.common.utils.Assert;
import com.sdy.common.utils.StringUtil;
import com.sdy.resdir.biz.model.RdImplementationOrder;
import com.sdy.resdir.biz.model.RdResourceDir;
import com.sdy.resdir.biz.param.AddResParam;
import com.sdy.resdir.biz.service.RdImplementationOrderService;
import com.sdy.resdir.biz.service.RdResourceDirService;
import com.sdy.resdir.biz.vo.*;
import com.sdy.usercenter.api.UserQueryApi;
import com.sdy.usercenter.api.dto.DeptDto;
import com.sdy.usercenter.api.dto.UserDTO;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import com.sdy.mvc.controller.BaseController;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 资源目录(总表)
 * </p>
 *
 * @author hyh
 * @since 2019-10-21
 */
@Slf4j
@RestController
@SuppressWarnings("unchecked")
@RequestMapping("/rdResourceDir")
@Api(tags = "资源目录API")
public class RdResourceDirController extends BaseController {
    @Autowired
    private RdResourceDirService rdResourceDirService;
    @Autowired
    private UserQueryApi userQueryApi;
    @Autowired
    private SsoService ssoService;
    @Autowired
    private RdImplementationOrderService rdImplementationOrderService;
    @Value("${res.dept.code}")
    private String deptCode;

    @ApiOperation(value = "资源目录页分页数据", response = RdResourceDir.class)
    @ApiImplicitParams(value = {
            @ApiImplicitParam(name = "resName", value = "模糊查询资源名称"),
            @ApiImplicitParam(name = "isOnline", value = "资源是否上线:1-已上线 2-未上线"),
            @ApiImplicitParam(name = "resType", value = "资源类型:1.服务接口类 2.服务页面类 3.数据教换类"),
            @ApiImplicitParam(name = "resLevel", value = "资源层级:1.省级 2.市级 3.区级"),
            @ApiImplicitParam(name = "resPower", value = "资源状态:1.公开 2.受限"),
            @ApiImplicitParam(name = "resPowerDept", value = "资源权限部门")}
    )
    @GetMapping("/resDirPageList")
    public Response<IPage<RdResourceDir>> resDirPageList(Page page, String resName, Integer isOnline, Integer resType, Integer resLevel, Integer resPower, Integer resPowerDept) throws Exception {
        if (null != resName) {
            resName = URLDecoder.decode(resName, "UTF-8");
        }
        IPage<RdResourceDir> rdResPageList = rdResourceDirService.page(page, Wrappers.<RdResourceDir>lambdaQuery()
                .orderByDesc(RdResourceDir::getCreateTime)
                .like(StringUtil.isNotBlank(resName) && StringUtil.isNotEmpty(resName), RdResourceDir::getResName, resName)
                .eq(null != isOnline, RdResourceDir::getCollectionSituation, isOnline)
                .eq(null != resType, RdResourceDir::getResType, resType)
                .eq(null != resLevel, RdResourceDir::getResLevel, resLevel)
                .eq(null != resPower, RdResourceDir::getResPower, resPower)
                .eq(null != resPowerDept, RdResourceDir::getResPowerDeptId, resPowerDept)
                .eq(RdResourceDir::getIsRelease, 1));
        return Response.success(rdResPageList);
    }


    @ApiOperation(value = "资源目录各类数据统计信息")
    @ApiImplicitParams(value = {
            @ApiImplicitParam(name = "resName", value = "模糊查询资源名称"),
            @ApiImplicitParam(name = "isOnline", value = "资源是否上线:1-已上线 2-未上线"),
            @ApiImplicitParam(name = "resType", value = "资源类型:1.服务接口类 2.服务页面类 3.数据教换类"),
            @ApiImplicitParam(name = "resLevel", value = "资源层级:1.省级 2.市级 3.区级"),
            @ApiImplicitParam(name = "resPower", value = "资源状态:1.公开 2.受限"),
            @ApiImplicitParam(name = "resPowerDept", value = "资源权限部门")}
    )
    @GetMapping("/getDataInfo")
    public Response<DataInfoVo> getDataInfo(String resName, Integer isOnline, Integer resType, Integer resLevel, Integer resPower, Integer resPowerDept) throws UnsupportedEncodingException {
        if (null != resName) {
            resName = URLDecoder.decode(resName, "UTF-8");
        }
        List<RdResourceDir> list = rdResourceDirService.list(Wrappers.<RdResourceDir>lambdaQuery()
                .like(StringUtil.isNotBlank(resName) && StringUtil.isNotEmpty(resName), RdResourceDir::getResName, resName)
                .eq(null != isOnline, RdResourceDir::getCollectionSituation, isOnline)
                .eq(null != resType, RdResourceDir::getResType, resType)
                .eq(null != resLevel, RdResourceDir::getResLevel, resLevel)
                .eq(null != resPower, RdResourceDir::getResPower, resPower)
                .eq(null != resPowerDept, RdResourceDir::getResPowerDeptId, resPowerDept)
                .eq(RdResourceDir::getIsRelease, 1));
        DataInfoVo dataInfoVo = new DataInfoVo();
        dataInfoVo.setServiceApiCount(list.stream().filter(rdResourceDir -> null != rdResourceDir.getResType() && rdResourceDir.getResType() == 1).collect(Collectors.toList()).size());
        dataInfoVo.setServicePageCount(list.stream().filter(rdResourceDir -> null != rdResourceDir.getResType() && rdResourceDir.getResType() == 2).collect(Collectors.toList()).size());
        dataInfoVo.setDataExchangeCount(list.stream().filter(rdResourceDir -> null != rdResourceDir.getResType() && rdResourceDir.getResType() == 3).collect(Collectors.toList()).size());
        dataInfoVo.setProvinceCount(list.stream().filter(rdResourceDir -> null != rdResourceDir.getResLevel() && rdResourceDir.getResLevel() == 1).collect(Collectors.toList()).size());
        dataInfoVo.setCityCount(list.stream().filter(rdResourceDir -> null != rdResourceDir.getResLevel() && rdResourceDir.getResLevel() == 2).collect(Collectors.toList()).size());
        dataInfoVo.setAreaCount(list.stream().filter(rdResourceDir -> null != rdResourceDir.getResLevel() && rdResourceDir.getResLevel() == 3).collect(Collectors.toList()).size());
        dataInfoVo.setOnLine(list.stream().filter(rdResourceDir -> null != rdResourceDir.getCollectionSituation() && rdResourceDir.getCollectionSituation() == 1).collect(Collectors.toList()).size());
        dataInfoVo.setOffLine(list.stream().filter(rdResourceDir -> null != rdResourceDir.getCollectionSituation() && rdResourceDir.getCollectionSituation() == 2).collect(Collectors.toList()).size());
        dataInfoVo.setIsPublic(list.stream().filter(rdResourceDir -> null != rdResourceDir.getResPower() && rdResourceDir.getResPower() == 1).collect(Collectors.toList()).size());
        dataInfoVo.setIsPrivate(list.stream().filter(rdResourceDir -> null != rdResourceDir.getResPower() && rdResourceDir.getResPower() == 2).collect(Collectors.toList()).size());
        DeptDto deptByCode = userQueryApi.getDeptByCode(deptCode);
        // 首先拿到数据资源局的信息
        List<RdResourceDir> collect = list.stream().filter(res -> null != res.getResPowerDeptId() && res.getResPowerDeptId().equals(deptByCode.getId())).collect(Collectors.toList());
        List<PowerDeptInfo> powerDeptInfos = new ArrayList<>();
        powerDeptInfos.add(new PowerDeptInfo().setId(deptByCode.getId()).setDept(deptByCode.getName()).setSize(collect.size()));
        Map<Integer, List<RdResourceDir>> deptInfo = list.stream().filter(res -> null != res.getResPowerDeptId() && !res.getResPowerDeptId().equals(deptByCode.getId())).collect(Collectors.groupingBy(RdResourceDir::getResPowerDeptId));
        for (Map.Entry<Integer, List<RdResourceDir>> entry : deptInfo.entrySet()) {
            powerDeptInfos.add(new PowerDeptInfo().setId(entry.getKey()).setDept(entry.getValue().get(0).getResPowerDept()).setSize(entry.getValue().size()));
        }
        dataInfoVo.setPowerDeptInfos(powerDeptInfos);
        return Response.success(dataInfoVo);
    }


    @ApiOperation(value = "资源详细数据", response = ResInfoVo.class)
    @ApiImplicitParams(value = {
            @ApiImplicitParam(name = "id", value = "根据资源ID查询该资源的详细信息")}
    )
    @GetMapping("/getResInfo")
    public Response<ResInfoVo> getResInfo(Integer id,String implementationWorkOrder) throws BizException {
        ResInfoVo resInfoVo = rdResourceDirService.getResInfoVo(id,implementationWorkOrder);
        return Response.success(resInfoVo);
    }


    @ApiOperation(value = "新增资源", response = ResInfoVo.class)
    @PostMapping("/addRes")
    public Response addRes(@RequestBody @ApiParam(name = "res", value = "新增资源") AddResParam res, HttpServletRequest request) throws Exception {
        Assert.isBlank(res.getResName(), "资源名称不可为空");
        UserInfo userInfo = ssoService.getUserInfo(request);
        UserDTO user = userQueryApi.getUser(userInfo.getUserId());
        res.setUserId(user.getId()).setDeptId(user.getOwnDeptId());
        int addRes = rdResourceDirService.addRes(res);
        return addRes == 1 ? Response.success() : Response.error();
    }

    @ApiOperation(value = "首页")
    @GetMapping(value = "getIndexPage")
    public Response<Map<String, IndexVO>> getIndexPage() {
        Map<String, IndexVO> rdResourceDirList = new HashMap(16);
        // 新上线资源
        List<RdResourceDir> newRdResourceDirs = rdResourceDirService.list(new LambdaQueryWrapper<RdResourceDir>()
                .eq(RdResourceDir::getIsRelease, 1)
                .eq(RdResourceDir::getCollectionSituation,1)
                .orderByDesc(RdResourceDir::getId)
                .last("limit 0,3"));
        IndexVO newResourceIndex = new IndexVO();
        newResourceIndex.setRdResourceDir(newRdResourceDirs);
        rdResourceDirList.put("newRdResourceDirs", newResourceIndex);
        List<RdImplementationOrder> rdImplementationOrders = rdImplementationOrderService.list(new LambdaQueryWrapper<RdImplementationOrder>()
                .last("limit 0,10"));
        List<ApplyRankVO> applyRanks = new ArrayList<>();
        // 申请排行榜
        getApplyRank(rdImplementationOrders, applyRanks);
        IndexVO applyRankIndex = new IndexVO();
        applyRankIndex.setApplyRankVO(applyRanks);
        rdResourceDirList.put("downloadRank", applyRankIndex);
        List<RdResourceDir> rdResourceDirs = rdResourceDirService.list(new LambdaQueryWrapper<RdResourceDir>()
                .last("limit 0,10"));
        List<ProvideVO> provideRanks = new ArrayList<>();
        //提供排行榜
        getProvideRank(rdResourceDirs, provideRanks);
        IndexVO provideRankIndex = new IndexVO();
        provideRankIndex.setProvideVO(provideRanks);
        rdResourceDirList.put("provideRank", provideRankIndex);
        return Response.success(rdResourceDirList);
    }

    /**
     * 获取提供排行榜
     *
     * @param rdResourceDirs
     * @param provideRanks
     */
    private void getProvideRank(List<RdResourceDir> rdResourceDirs, List<ProvideVO> provideRanks) {
        if (!rdResourceDirs.isEmpty()) {
            List<RdResourceDir> rdResourceDirList=new ArrayList<>();
            for (RdResourceDir rdResourceDir:rdResourceDirs) {
                if (StringUtil.isNotBlank(rdResourceDir.getResSourceDept())){
                    rdResourceDirList.add(rdResourceDir);
                }
            }
            Map<Integer, List<RdResourceDir>> resSourceDeptMap = rdResourceDirList.stream().collect(Collectors.groupingBy(RdResourceDir::getResSourceDeptId));
            Map<Integer, Integer> keyAndValue = new HashMap<>(16);
            for (Map.Entry<Integer, List<RdResourceDir>> provideNumber : resSourceDeptMap.entrySet()) {
                keyAndValue.put(provideNumber.getKey(), provideNumber.getValue().size());
            }
            List<Map.Entry<Integer, Integer>> list = maySort(keyAndValue);
            for (Map.Entry<Integer, Integer> getValues : list) {
                ProvideVO provideVO = new ProvideVO();
                RdResourceDir rdResourceDir = rdResourceDirService.getOne(new LambdaQueryWrapper<RdResourceDir>()
                        .eq(RdResourceDir::getResSourceDeptId, getValues.getKey()));
                if (rdResourceDir != null) {
                    provideVO.setRankNumber(list.size());
                    provideVO.setProvider(rdResourceDir.getResSourceDept());
                    provideVO.setProvideNumber(getValues.getValue());
                    provideRanks.add(provideVO);
                }
            }
        }
    }

    /**
     * 获取申请排行榜
     *
     * @param rdImplementationOrders
     * @param applyRanks
     */
    private void getApplyRank(List<RdImplementationOrder> rdImplementationOrders, List<ApplyRankVO> applyRanks) {
        if (!rdImplementationOrders.isEmpty()) {
            Map<Integer, Integer> keyAndValue = new HashMap<>(16);
            Map<Integer, List<RdImplementationOrder>> applyNumbers = rdImplementationOrders.stream().collect(Collectors.groupingBy(RdImplementationOrder::getResId));
            for (Map.Entry<Integer, List<RdImplementationOrder>> applyNumber : applyNumbers.entrySet()) {
                keyAndValue.put(applyNumber.getKey(), applyNumber.getValue().size());
            }
            // 获得排序后的资源列表
            List<Map.Entry<Integer, Integer>> list = maySort(keyAndValue);
            //
            for (Map.Entry<Integer, Integer> getValues : list) {
                ApplyRankVO applyRankVO = new ApplyRankVO();
                RdImplementationOrder rdImplementationOrder = rdImplementationOrderService.getOne(
                        new LambdaQueryWrapper<RdImplementationOrder>().eq(RdImplementationOrder::getResId, getValues.getKey()));
                if (rdImplementationOrder != null) {
                    applyRankVO.setRankNumber(list.size());
                    applyRankVO.setResName(rdImplementationOrder.getResName());
                    applyRankVO.setDownloadNumber(getValues.getValue());
                    applyRanks.add(applyRankVO);
                }
            }
        }
    }

    /**
     * 排行榜排序
     *
     * @param keyAndValue
     * @return
     */
    private List<Map.Entry<Integer, Integer>> maySort(Map<Integer, Integer> keyAndValue) {
        List<Map.Entry<Integer, Integer>> list = new ArrayList(keyAndValue.entrySet());
        Collections.sort(list, (o1, o2) -> o2.getValue().compareTo(o1.getValue()));
        return list;
    }
}
